{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Yu7u1mNfnxVP"
      },
      "source": [
        "**Copyright 2019 The Sonnet Authors. All Rights Reserved.**\n",
        "\n",
        "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "you may not use this file except in compliance with the License.\n",
        "You may obtain a copy of the License at\n",
        "\n",
        "   http://www.apache.org/licenses/LICENSE-2.0\n",
        "\n",
        "Unless required by applicable law or agreed to in writing, software\n",
        "distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or  implied.\n",
        "See the License for the specific language governing permissions and\n",
        "limitations under the License.\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "WAfR3cvnoGMB"
      },
      "source": [
        "# Preamble"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "4FqOAJb_jJR9"
      },
      "outputs": [],
      "source": [
        "import sys\n",
        "assert sys.version_info \u003e= (3, 6), \"Sonnet 2 requires Python \u003e=3.6\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 136
        },
        "colab_type": "code",
        "id": "XnWX2azUDuCl",
        "outputId": "8516864f-06cb-4dd5-946c-adeae1e17f3a"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: dm-sonnet==2.0.0b0 in /usr/local/lib/python3.6/dist-packages (2.0.0b0)\n",
            "Requirement already satisfied: gast==0.2.2 in /usr/local/lib/python3.6/dist-packages (0.2.2)\n",
            "Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (4.28.1)\n",
            "Requirement already satisfied: wrapt\u003e=1.11.1 in /tensorflow-2.0.0-rc1/python3.6 (from dm-sonnet==2.0.0b0) (1.11.2)\n",
            "Requirement already satisfied: numpy\u003e=1.16.3 in /tensorflow-2.0.0-rc1/python3.6 (from dm-sonnet==2.0.0b0) (1.17.2)\n",
            "Requirement already satisfied: absl-py\u003e=0.7.1 in /tensorflow-2.0.0-rc1/python3.6 (from dm-sonnet==2.0.0b0) (0.8.0)\n",
            "Requirement already satisfied: six\u003e=1.12.0 in /tensorflow-2.0.0-rc1/python3.6 (from dm-sonnet==2.0.0b0) (1.12.0)\n"
          ]
        }
      ],
      "source": [
        "!pip install dm-sonnet tqdm"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "mn5ofK4-D1Qk"
      },
      "outputs": [],
      "source": [
        "import sonnet as snt\n",
        "import tensorflow as tf\n",
        "import tensorflow_datasets as tfds"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        },
        "colab_type": "code",
        "id": "Rpp_houJEHr9",
        "outputId": "9e7597ba-d8a5-483e-b415-5729ef3102e8"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TensorFlow version: 2.0.0-rc1\n",
            "    Sonnet version: 2.0.0b0\n"
          ]
        }
      ],
      "source": [
        "print(\"TensorFlow version: {}\".format(tf.__version__))\n",
        "print(\"    Sonnet version: {}\".format(snt.__version__))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "5RmHUmz1padR"
      },
      "source": [
        "Finally lets take a quick look at the GPUs we have available:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "colab_type": "code",
        "id": "TXoxEvKepdw2",
        "outputId": "da76b78b-274e-462d-fa47-89d626a4370f"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " Tesla K80\n"
          ]
        }
      ],
      "source": [
        "!grep Model: /proc/driver/nvidia/gpus/*/information | awk '{$1=\"\";print$0}'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "UYYmqvOKfNbk"
      },
      "source": [
        "# Dataset\n",
        "\n",
        "We need to get our dataset in a state where we can iterate over it easily. The TensorFlow Datasets package provides a simple API for this. It will download the dataset and prepare it for us to speedily process on a GPU. We can also add our own pre-processing functions to mutate the dataset before our model sees it:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "UkBRriaQEr4z"
      },
      "outputs": [],
      "source": [
        "batch_size = 100\n",
        "\n",
        "def process_batch(images, labels):\n",
        "  images = tf.squeeze(images, axis=[-1])\n",
        "  images = tf.cast(images, dtype=tf.float32)\n",
        "  images = ((images / 255.) - .5) * 2.\n",
        "  return images, labels\n",
        "\n",
        "def mnist(split):\n",
        "  dataset = tfds.load(\"mnist\", split=split, as_supervised=True)\n",
        "  dataset = dataset.map(process_batch)\n",
        "  dataset = dataset.batch(batch_size)\n",
        "  dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)\n",
        "  dataset = dataset.cache()\n",
        "  return dataset\n",
        "\n",
        "mnist_train = mnist(\"train\").shuffle(10)\n",
        "mnist_test = mnist(\"test\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "JfOCWVGEfgcq"
      },
      "source": [
        "MNIST contains `28x28` greyscale handwritten digits. Let's take a look at one:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 269
        },
        "colab_type": "code",
        "id": "I_yM0TVjFCZq",
        "outputId": "54959260-c8fc-4e39-ea54-e566e9122893"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "\u003cFigure size 432x288 with 1 Axes\u003e"
            ]
          },
          "metadata": {
            "tags": []
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "images, _ = next(iter(mnist_test))\n",
        "plt.imshow(images[0]);"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "d7bsizs5gK3K"
      },
      "source": [
        "# Sonnet\n",
        "\n",
        "The next step is to define a model. In Sonnet everything that contains TensorFlow variables (`tf.Variable`) extends `snt.Module`, this includes low level neural network components (e.g. `snt.Linear`,  `snt.Conv2D`), larger nets containing subcomponents (e.g. `snt.nets.MLP`), optimizers (e.g. `snt.optimizers.Adam`) and whatever else you can think of.\n",
        "\n",
        "Modules provide a simple abstraction for storing parameters (and `Variable`s used for other purposes, like for storing moving avergages in `BatchNorm`).\n",
        "\n",
        "To find all the parameters for a given module, simply do: `module.variables`. This will return a `tuple` of all the parameters that exist for this module, or any module it references:"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "GrN37pi1o4HT"
      },
      "source": [
        "## Building the model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "c6XoN56S2lSW"
      },
      "source": [
        "In Sonnet you build neural networks out of `snt.Module`s. In this case we'll build a multi-layer perceptron as a new class with a `__call__` method that computes the logits by passing the input through a number of fully connected layers, with a ReLU non-linearity."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "hgjyB9yhFclD"
      },
      "outputs": [],
      "source": [
        "class MLP(snt.Module):\n",
        "\n",
        "  def __init__(self):\n",
        "    super(MLP, self).__init__()\n",
        "    self.flatten = snt.Flatten()\n",
        "    self.hidden1 = snt.Linear(1024, name=\"hidden1\")\n",
        "    self.hidden2 = snt.Linear(1024, name=\"hidden2\")\n",
        "    self.logits = snt.Linear(10, name=\"logits\")\n",
        "\n",
        "  def __call__(self, images):\n",
        "    output = self.flatten(images)\n",
        "    output = tf.nn.relu(self.hidden1(output))\n",
        "    output = tf.nn.relu(self.hidden2(output))\n",
        "    output = self.logits(output)\n",
        "    return output"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "0i03px8y8gf7"
      },
      "source": [
        "Now we'll create an instance of our class whose weights will be randomly initialized. We'll train this MLP such that it learns to recognize digits in the MNIST dataset."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "colab_type": "code",
        "id": "XqL8oIMqGAnU",
        "outputId": "96efc445-d7bb-45db-f6b1-5aa4a8b72dcb"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "MLP()"
            ]
          },
          "execution_count": 11,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "mlp = MLP()\n",
        "mlp"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "snzkUUh9oXPy"
      },
      "source": [
        "## Using the model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "On8wI6VwpDPm"
      },
      "source": [
        "Let's feed an example input through the model and see what it predicts. Since the model is randomly initialized there is a 1/10 chance that it will predict the right class!"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 286
        },
        "colab_type": "code",
        "id": "4T-qmIc0GHfP",
        "outputId": "316f41f2-319c-452e-a132-5006b732e86b"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Predicted class: 0 actual class: 6\n"
          ]
        },
        {
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "\u003cFigure size 432x288 with 1 Axes\u003e"
            ]
          },
          "metadata": {
            "tags": []
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "images, labels = next(iter(mnist_test))\n",
        "logits = mlp(images)\n",
        "  \n",
        "prediction = tf.argmax(logits[0]).numpy()\n",
        "actual = labels[0].numpy()\n",
        "print(\"Predicted class: {} actual class: {}\".format(prediction, actual))\n",
        "plt.imshow(images[0]);"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "V297xpzfobXK"
      },
      "source": [
        "## Training the model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "WTrv-jn4pPSx"
      },
      "source": [
        "To train the model we need an optimizer. For this simple example we'll use Stochastic Gradient Descent which is implemented in the `SGD` optimizer. To compute gradients we'll use a `tf.GradientTape` which allows us to selectively record gradients only for the computation we want to back propagate through:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "cellView": "form",
        "colab": {},
        "colab_type": "code",
        "id": "V7gi8NQ-WZOl"
      },
      "outputs": [],
      "source": [
        "#@title Utility function to show progress bar.\n",
        "from tqdm import tqdm\n",
        "\n",
        "# MNIST training set has 60k images.\n",
        "num_images = 60000\n",
        "\n",
        "def progress_bar(generator):\n",
        "  return tqdm(\n",
        "      generator,\n",
        "      unit='images',\n",
        "      unit_scale=batch_size,\n",
        "      total=(num_images // batch_size) * num_epochs)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 85
        },
        "colab_type": "code",
        "id": "UUkshshiK6Eq",
        "outputId": "edf09c6d-cc08-482d-98d8-45778082ed0b"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|██████████| 600000/600000 [01:02\u003c00:00, 9660.48images/s] "
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "\n",
            "Final loss: 0.039747316390275955\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "source": [
        "opt = snt.optimizers.SGD(learning_rate=0.1)\n",
        "\n",
        "num_epochs = 10\n",
        "\n",
        "def step(images, labels):\n",
        "  \"\"\"Performs one optimizer step on a single mini-batch.\"\"\"\n",
        "  with tf.GradientTape() as tape:\n",
        "    logits = mlp(images)\n",
        "    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,\n",
        "                                                          labels=labels)\n",
        "    loss = tf.reduce_mean(loss)\n",
        "\n",
        "  params = mlp.trainable_variables\n",
        "  grads = tape.gradient(loss, params)\n",
        "  opt.apply(grads, params)\n",
        "  return loss\n",
        "\n",
        "for images, labels in progress_bar(mnist_train.repeat(num_epochs)):\n",
        "  loss = step(images, labels)\n",
        "\n",
        "print(\"\\n\\nFinal loss: {}\".format(loss.numpy()))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "2K0_eoR8og-G"
      },
      "source": [
        "## Evaluating the model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Cm_9RMJopgWc"
      },
      "source": [
        "We'll do very simple analysis of the model to get a feeling for how well it does against this dataset:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "colab_type": "code",
        "id": "PM7IPcOeXtxH",
        "outputId": "fc983d03-f92c-4002-f7df-514c251bd300"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Got 9767/10000 (97.67%) correct\n"
          ]
        }
      ],
      "source": [
        "total = 0\n",
        "correct = 0\n",
        "for images, labels in mnist_test:\n",
        "  predictions = tf.argmax(mlp(images), axis=1)\n",
        "  correct += tf.math.count_nonzero(tf.equal(predictions, labels))\n",
        "  total += images.shape[0]\n",
        "\n",
        "print(\"Got %d/%d (%.02f%%) correct\" % (correct, total, correct / total * 100.))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Lnkc55PtqA_I"
      },
      "source": [
        "To understand the result a bit better, lets take a look at a small sample of where the model correctly identified the digits:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 0,
      "metadata": {
        "cellView": "form",
        "colab": {},
        "colab_type": "code",
        "id": "eFro_RB4YR-X"
      },
      "outputs": [],
      "source": [
        "#@title Utility function to show a sample of images.\n",
        "def sample(correct, rows, cols):\n",
        "  n = 0\n",
        "\n",
        "  f, ax = plt.subplots(rows, cols)\n",
        "  if rows \u003e 1:    \n",
        "    ax = tf.nest.flatten([tuple(ax[i]) for i in range(rows)])\n",
        "  f.set_figwidth(14)\n",
        "  f.set_figheight(4 * rows)\n",
        "\n",
        "\n",
        "  for images, labels in mnist_test:\n",
        "    predictions = tf.argmax(mlp(images), axis=1)\n",
        "    eq = tf.equal(predictions, labels)\n",
        "    for i, x in enumerate(eq):\n",
        "      if x.numpy() == correct:\n",
        "        label = labels[i]\n",
        "        prediction = predictions[i]\n",
        "        image = images[i]\n",
        "\n",
        "        ax[n].imshow(image)\n",
        "        ax[n].set_title(\"Prediction:{}\\nActual:{}\".format(prediction, label))\n",
        "\n",
        "        n += 1\n",
        "        if n == (rows * cols):\n",
        "          break\n",
        "\n",
        "    if n == (rows * cols):\n",
        "      break"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 214
        },
        "colab_type": "code",
        "id": "PSamdka2dodW",
        "outputId": "e5c521a6-3d5b-4be6-f371-a2c7a87ae124"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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\n17ZRHmnNoJn1MLOpZva2ma0ws2fN7ItdvV1URlpzmGzvZjNbbGYfmdmrZnZCObaL8kp5Bj9ucWsy\nsyvLsW2UV1pzWIufyQxk2mBmW0jaU7lrDxxS0c4UYGb7S/qRpK9L6itpL0lvVLRTKKmUZ7BeuSsU\n7y2pv6TzJd2e9BlVJOU5lHLXXtjC3fsp17+LzGyXCvcJJZT2DLp7nw03SUMlrRYXu6w6Kc9hzX0m\nM5Bp27GSZkqaptzFqyRJZtbLzC5LRr1/M7PHzayXpMeSJh8mf5HZzcwmm9nNzR6bNzo3s68nR1RW\nmNkbZnZyO/r3A0kXuvtMd1/v7ovcfVFnnzRSJbUZdPeV7j7Z3d9K8nevpDcl8Qtk9UltDiXJ3ee6\n+9oNi8ltq049Y6RNqjPYwlckLZP0pw4+HumV2hzW4mcyA5m2HSvpluT2T2Y2JKlfqlwwPqfc1Vi/\nI2m9ckdEJGnT5C8zTxaxjWWSviypn3JHVn5sZjsXamhm15jZNcnPdZImSNrMzOab2UIzuyr5j4Pq\nkdoMFrhviKRtJM0t5okhU1Kfw6S2StLLkhZLuq8dzw/pl/oMNjNJ0s+dq45Xo8zksBY+k8s2jyOL\nzGwPSWMk3e7u75nZ65L+1cx+IukbknZtdvTjieQx7d6Ou/+22eIfzewB5Q5bPlOg7TebLQ6R1CDp\nq0n7dZJmKHco8fvt7ghSJwMZbN7XBuV27NPd/eV2dwKplZUcuvs3zewMSbtJ+ryktS3bIJuyksFk\nu2OU+2rP8e3uAFItYzmsic9kjshs3CRJD7j7e8nyL5LaYEk9Jb1eio2Y2RfNbKaZfWBmH0o6KNlG\nW1Yn/17p7ouTfl6ePB7VIe0Z3PD4bpJukvSJpNNL0SekSiZyKEnu3uTuj0saKenUUvQLqZCZDEo6\nRtLj7v5mKfqEVMlEDmvpM5kjMq1Ivp71NUl1ZrYkKfeQtKmkYZLWKPf96+daPLTQYeSVkno3Wx7a\nbDs9JN2h3KHKGe6+zszultTmEN7dl1vuFHzNt8lh7CqRhQwmjzdJU5U7QniQu68r5nHIhqzksIB6\nMUemKmQwg8dKuqSdj0HKZSWHtfaZzBGZ1h0mqUnSeEk7JrftlJu4d6ykGyRdbmbDzawumbzVQ9K7\nyn0ncstm63pW0l5mNtrM+kv692b3dVfuP8K7khotd5q8A9rRzxslnWFmm5vZAEn/June9j9dpFBW\n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\n5MF1f//wc0EAAAAASUVORK5CYII=\n",
            "text/plain": [
              "\u003cFigure size 1008x288 with 5 Axes\u003e"
            ]
          },
          "metadata": {
            "tags": []
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "sample(correct=True, rows=1, cols=5)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "hzHp02F_pzdh"
      },
      "source": [
        "Now lets take a look at where it incorrectly classifies the input. MNIST has some rather dubious handwriting, I'm sure you'll agree that some of the samples below are a little ambiguous:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 451
        },
        "colab_type": "code",
        "id": "KQe5Q9LNdnb0",
        "outputId": "7f28c377-2226-468e-e388-a1cb649a26f5"
      },
      "outputs": [
        {
          "data": {
            "image/png": "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\ny70XQugWQqgvdZui/1T3mtlSM1tkZles+w+G8qnyDD5mZqui1/6pmb1Z6m2gMNWcw2h7h5jZTDP7\nzMzeNrPd2mI7aFq1ZtDMOprZdWY218xWmNk0Mxtbym2gcNWaw2hbnzZ61JvZ5aXeTluquo5M5Bsh\nhG6StpM0RtLZ2U9aRiW+NxMkLZbUV9JoSbtL+lGsLape1ZpBSTo52il3CyFsHndjqlxV5tDM9pH0\nW0nHSOou6SuS3om1UdWrGjPYTtI8ZX4Hb6DMa77VzIbE2KZqV405VNbv4m6SNpX0uaS/x9ysFqm4\nD6UlQggLJP1L0lbRN8UXmNlTklZKGmpmG0Tfmiw0swVmdv66Q3tmVmtmF5nZEjN7R9IB2euO1ndc\n1vQPo2//VpjZDDPbzsz+ImmQpH9GPeEz8xyK7GdmU8zsYzObbWY/zFrneDO71cz+HK13upmNWc9L\n3kzSrSGEVSGERZLuk/SFkryZKEoVZhAJVIU5/JWkc0MIz4YQGkIIC6L3ADGppgyGED4LIYwPIcyJ\n8ne3pHclbV/SNxUtVk05zOO7ynzZ/e/i38EYhBCq6iFpjqS9o58HSpou6TxJj0l6T5k/7NtJai/p\nDknXSOoqqbek5yUdHy17gqQ3onX0kvSopCCpXfT8Y5KOi34+SNICSTtIMknDJQ1u3J5oekij9Tyh\nzJGUTsocRflQ0p7Rc+MlrZK0v6RaSb+R9GzWuiZImpA1fbykP0vqIqm/pNclfTvuz6TaHlWewcei\n5ZdIekrSHnF/HtX6qNYcRs+vkXSWpNmS5ku6QlLnuD+TantUawbzvA99omW3iPszqcYHOfzPc49I\nGh/359Hizy/uBsQU2E8lLZM0N/pQO0cBOzdrvj6SVivrl5ukQyU9mvWBn5D13NfWE9j7JZ26nvbk\nDWz0n6FeUves538jaVL083hJD2U9N0rS5+t57VtKelHS2mgbkyRZ3J9JtT2qPINfUuZUno6SjpK0\nQtKwuD+TanxUaw4l9YvWO1WZ02w3VqZTfUHcn0m1Pao1g4222V7SQ5KuifvzqNYHOQySNDha72Zx\nfx4tfVTrQO8DQwgPZRfMTMqcs7rOYGV2MAuj56TMqXjr5unXaP6569neQElvF9HOfpI+DiGsaLSd\n7MOEi7J+Ximpk5m1CyGszV6RZc7tvE/SREm7SOom6XplzhM/s4i2oXWqLoOSFEJ4Lmtyspkdqsw3\n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\n",
            "text/plain": [
              "\u003cFigure size 1008x576 with 10 Axes\u003e"
            ]
          },
          "metadata": {
            "tags": []
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "sample(correct=False, rows=2, cols=5)"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [],
      "name": "Sonnet 2 \"Hello, world!\" (aka. MLP on MNIST)",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
